﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;

namespace AuthenticationService.Client.Controls
{
    [TemplatePart(Name = "Core", Type = typeof(FrameworkElement))]
    [TemplatePart(Name = "LoginContainer", Type = typeof(FrameworkElement))]
    [TemplatePart(Name = "LoggingInContainer", Type = typeof(FrameworkElement))]
    [TemplatePart(Name = "LoginButton", Type = typeof(ButtonBase))]
    [TemplatePart(Name = "CancelButton", Type = typeof(ButtonBase))]
    [TemplatePart(Name = "RegisterButton", Type = typeof(ButtonBase))]
    [TemplatePart(Name = "GetPasswordButton", Type = typeof(ButtonBase))]
    [TemplatePart(Name = "UsernameTextbox", Type = typeof(TextBox))]
    [TemplatePart(Name = "PasswordTextbox", Type = typeof(PasswordBox))]
    [TemplateVisualState(Name = "LoggedOut", GroupName = "LoginStates")]
    [TemplateVisualState(Name = "LoggingIn", GroupName = "LoginStates")]
    public class LoginControl : Control
    {
        private FrameworkElement corePart;
        private FrameworkElement loginContainerPart;
        private FrameworkElement loggingInContainerPart;
        private ButtonBase loginButtonPart;
        private ButtonBase cancelButtonPart;
        private ButtonBase registerButtonPart;
        private ButtonBase getPasswordButtonPart;
        private TextBox usernameTextboxPart;
        private PasswordBox passwordTextboxPart;
        private bool isLoggingIn;
        public event RoutedEventHandler Login;
        public event RoutedEventHandler Cancel;
        public event RoutedEventHandler GetPassword;
        public event RoutedEventHandler Register;

        public static readonly DependencyProperty UsernameProperty = DependencyProperty.Register("Username", typeof(string), typeof(LoginControl), new PropertyMetadata(LoginControl.OnUsernameChanged));
        public string Username
        {
            get
            {
                return (string)GetValue(UsernameProperty);
            }
            set
            {
                SetValue(UsernameProperty, value);
                GoToState(true);
            }
        }
        private static void OnUsernameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            LoginControl control = d as LoginControl;
            string un = String.Empty;
            try
            {
                un = e.NewValue as string;
            }
            catch
            {
            }
            control.Username = un;
        }

        public static readonly DependencyProperty PasswordProperty = DependencyProperty.Register("Password", typeof(string), typeof(LoginControl), new PropertyMetadata(LoginControl.OnPasswordChanged));
        public string Password
        {
            get
            {
                return (string)GetValue(PasswordProperty);
            }
            set
            {
                SetValue(PasswordProperty, value);
                GoToState(true);
            }
        }
        private static void OnPasswordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            LoginControl control = d as LoginControl;
            string pass = String.Empty;
            try
            {
                pass = e.NewValue as string;
            }
            catch
            {
            }
            control.Password = pass;
        }

        public LoginControl()
        {
            this.DefaultStyleKey = typeof(LoginControl);
        }
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            CorePart = GetTemplateChild("Core") as FrameworkElement;
            LoginContainerPart = GetTemplateChild("LoginContainer") as FrameworkElement;
            LoggingInContainerPart = GetTemplateChild("LoggingInContainer") as FrameworkElement;
            LoginButtonPart = GetTemplateChild("LoginButton") as ButtonBase;
            CancelButtonPart = GetTemplateChild("CancelButton") as ButtonBase;
            GetPasswordButtonPart = GetTemplateChild("GetPasswordButton") as ButtonBase;
            RegisterButtonPart = GetTemplateChild("RegisterButton") as ButtonBase;
            UsernameTextboxPart = GetTemplateChild("UsernameTextbox") as TextBox;
            PasswordTextboxPart = GetTemplateChild("PasswordTextbox") as PasswordBox;
            GoToState(false);
        }

        public void ResetState()
        {
            isLoggingIn = false;
            GoToState(false);
            UsernameTextboxPart.UpdateLayout();
            UsernameTextboxPart.Focus();
        }

        private void GoToState(bool useTransitions)
        {
            if (isLoggingIn)
            {
                VisualStateManager.GoToState(this, "LoggingIn", useTransitions);
            }
            else
            {
                VisualStateManager.GoToState(this, "LoggedOut", useTransitions);
            }
        }

        private FrameworkElement CorePart
        {
            get
            {
                return corePart;
            }
            set
            {
                FrameworkElement oldCorePart = corePart;

                //detach event handlers from existing part
                if (oldCorePart != null)
                {

                }

                corePart = value;

                //attach event handlers to part
                if (corePart != null)
                {
                }
            }
        }

        private FrameworkElement LoginContainerPart
        {
            get
            {
                return loginContainerPart;
            }
            set
            {
                FrameworkElement oldLoginContainerPart = loginContainerPart;

                //detach event handlers from existing part
                if (oldLoginContainerPart != null)
                {

                }

                loginContainerPart = value;

                //attach event handlers to part
                if (loginContainerPart != null)
                {
                }
            }
        }

        private FrameworkElement LoggingInContainerPart
        {
            get
            {
                return loggingInContainerPart;
            }
            set
            {
                FrameworkElement oldLoggingInContainerPart = loggingInContainerPart;

                //detach event handlers from existing part
                if (oldLoggingInContainerPart != null)
                {

                }

                loggingInContainerPart = value;

                //attach event handlers to part
                if (loggingInContainerPart != null)
                {
                }
            }
        }

        private ButtonBase LoginButtonPart
        {
            get
            {
                return loginButtonPart;
            }
            set
            {
                ButtonBase oldLoginButtonPart = loginButtonPart;

                //detach event handlers from existing part
                if (oldLoginButtonPart != null)
                {
                    oldLoginButtonPart.Click -= new RoutedEventHandler(loginButtonPart_Click);
                }

                loginButtonPart = value;

                //attach event handlers to part
                if (loginButtonPart != null)
                {
                    loginButtonPart.Click += new RoutedEventHandler(loginButtonPart_Click);
                }
            }
        }

        private ButtonBase CancelButtonPart
        {
            get
            {
                return cancelButtonPart;
            }
            set
            {
                ButtonBase oldCancelButtonPart = cancelButtonPart;

                //detach event handlers from existing part
                if (oldCancelButtonPart != null)
                {
                    oldCancelButtonPart.Click -= new RoutedEventHandler(cancelButtonPart_Click);
                }

                cancelButtonPart = value;

                //attach event handlers to part
                if (cancelButtonPart != null)
                {
                    cancelButtonPart.Click += new RoutedEventHandler(cancelButtonPart_Click);
                }
            }
        }

        private ButtonBase GetPasswordButtonPart
        {
            get
            {
                return getPasswordButtonPart;
            }
            set
            {
                ButtonBase oldGetPasswordButtonPart = getPasswordButtonPart;

                //detach event handlers from existing part
                if (oldGetPasswordButtonPart != null)
                {
                    oldGetPasswordButtonPart.Click -= new RoutedEventHandler(getPasswordButtonPart_Click);
                }

                getPasswordButtonPart = value;

                //attach event handlers to part
                if (getPasswordButtonPart != null)
                {
                    getPasswordButtonPart.Click += new RoutedEventHandler(getPasswordButtonPart_Click);
                }
            }
        }

        private ButtonBase RegisterButtonPart
        {
            get
            {
                return registerButtonPart;
            }
            set
            {
                ButtonBase oldRegisterButtonPart = registerButtonPart;

                //detach event handlers from existing part
                if (oldRegisterButtonPart != null)
                {
                    oldRegisterButtonPart.Click -= new RoutedEventHandler(registerButtonPart_Click);
                }

                registerButtonPart = value;

                //attach event handlers to part
                if (registerButtonPart != null)
                {
                    registerButtonPart.Click += new RoutedEventHandler(registerButtonPart_Click);
                }
            }
        }

        private TextBox UsernameTextboxPart
        {
            get
            {
                return usernameTextboxPart;
            }
            set
            {
                TextBox oldUsernameTextboxPart = usernameTextboxPart;

                //detach event handlers from existing part
                if (oldUsernameTextboxPart != null)
                {
                    oldUsernameTextboxPart.KeyDown -= new KeyEventHandler(usernameTextboxPart_KeyDown);
                    oldUsernameTextboxPart.TextChanged -= new TextChangedEventHandler(usernameTextboxPart_TextChanged);
                }

                usernameTextboxPart = value;

                //attach event handlers to part
                if (usernameTextboxPart != null)
                {
                    usernameTextboxPart.KeyDown += new KeyEventHandler(usernameTextboxPart_KeyDown);
                    usernameTextboxPart.TextChanged += new TextChangedEventHandler(usernameTextboxPart_TextChanged);
                }
            }
        }

        void usernameTextboxPart_TextChanged(object sender, TextChangedEventArgs e)
        {
            Username = ((TextBox)sender).Text;
        }

        void usernameTextboxPart_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                OnLogin(new RoutedEventArgs());
            }
        }

        private PasswordBox PasswordTextboxPart
        {
            get
            {
                return passwordTextboxPart;
            }
            set
            {
                PasswordBox oldPasswordTextboxPart = passwordTextboxPart;

                //detach event handlers from existing part
                if (oldPasswordTextboxPart != null)
                {
                    oldPasswordTextboxPart.KeyDown -= new KeyEventHandler(passwordTextboxPart_KeyDown);
                    oldPasswordTextboxPart.PasswordChanged -= new RoutedEventHandler(passwordTextboxPart_PasswordChanged);
                }

                passwordTextboxPart = value;

                //attach event handlers to part
                if (passwordTextboxPart != null)
                {
                    passwordTextboxPart.KeyDown += new KeyEventHandler(passwordTextboxPart_KeyDown);
                    passwordTextboxPart.PasswordChanged += new RoutedEventHandler(passwordTextboxPart_PasswordChanged);
                }
            }
        }

        void passwordTextboxPart_PasswordChanged(object sender, RoutedEventArgs e)
        {
            Password = ((PasswordBox)sender).Password;
        }

        void passwordTextboxPart_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                OnLogin(new RoutedEventArgs());
            }
        }

        private void OnLogin(RoutedEventArgs e)
        {
            if (Login != null)
            {
                Login(this, e);
            }
        }

        void loginButtonPart_Click(object sender, RoutedEventArgs e)
        {
            isLoggingIn = true;
            GoToState(true);
            OnLogin(new RoutedEventArgs());
        }

        void cancelButtonPart_Click(object sender, RoutedEventArgs e)
        {
            ResetState();
            if (Cancel != null)
            {
                Cancel(this, e);
            }
        }

        void getPasswordButtonPart_Click(object sender, RoutedEventArgs e)
        {
            if (GetPassword != null)
            {
                GetPassword(this, e);
            }
        }

        void registerButtonPart_Click(object sender, RoutedEventArgs e)
        {
            if (Register != null)
            {
                Register(this, e);
            }
        }
    }
}
